home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / aros / source / exec / semaphores / src / releasesemaphore.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  3.5 KB  |  145 lines

  1. /*
  2.     $Id$
  3.     $Log$
  4.     Desc:
  5.     Lang: english
  6. */
  7. #include "exec_intern.h"
  8. #include "semaphores.h"
  9.  
  10. /*****************************************************************************
  11.  
  12.     NAME */
  13.     #include <exec/semaphores.h>
  14.     #include <clib/exec_protos.h>
  15.  
  16.     __AROS_LH1(void, ReleaseSemaphore,
  17.  
  18. /*  SYNOPSIS */
  19.     __AROS_LA(struct SignalSemaphore *, sigSem, A0),
  20.  
  21. /*  LOCATION */
  22.     struct ExecBase *, SysBase, 95, Exec)
  23.  
  24. /*  FUNCTION
  25.     Releases a lock on a semaphore obtained with either ObtainSemaphore(),
  26.     ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
  27.     Each call to one of those functions must be accompanied with one
  28.     call to ReleasSemaphore().
  29.  
  30.     INPUTS
  31.     sigSem - pointer to semaphore structure
  32.  
  33.     RESULT
  34.  
  35.     NOTES
  36.     This function preserves all registers.
  37.  
  38.     EXAMPLE
  39.  
  40.     BUGS
  41.  
  42.     SEE ALSO
  43.  
  44.     INTERNALS
  45.  
  46.     HISTORY
  47.     29-10-95    digulla automatically created from
  48.                 exec_lib.fd and clib/exec_protos.h
  49.     22-01-96    fleischer implementation
  50.  
  51. *****************************************************************************/
  52. {
  53.     __AROS_FUNC_INIT
  54.     __AROS_BASE_EXT_DECL(struct ExecBase *,SysBase)
  55.  
  56.     /* Arbitrate for the semaphore structure */
  57.     Forbid();
  58.  
  59.     /* Lower the use count. >0 means exclusive, <0 shared locked */
  60.     if(sigSem->ss_NestCount>0)
  61.     sigSem->ss_NestCount--;
  62.     else
  63.     sigSem->ss_NestCount++;
  64.  
  65.     /*
  66.     Now if the semaphore is free and there are other tasks waiting
  67.     wake them up.
  68.     */
  69.     if(!sigSem->ss_NestCount&&sigSem->ss_WaitQueue.mlh_Head->mln_Succ!=NULL)
  70.     {
  71.     /* Get first node in the waiting list */
  72.     struct SemaphoreNode *sn;
  73.     sn=(struct SemaphoreNode *)sigSem->ss_WaitQueue.mlh_Head;
  74.  
  75.     /* Is it a shared lock? */
  76.     if((ULONG)sn->node.ln_Name!=SM_EXCLUSIVE)
  77.     {
  78.         /* Yes. Process all shared locks in the list. */
  79.         while(sn->node.ln_Succ!=NULL)
  80.         {
  81.         /* Remember node */
  82.         struct SemaphoreNode *on=sn;
  83.  
  84.         /* Get next node now because there is a Remove() lurking */
  85.         sn=(struct SemaphoreNode *)sn->node.ln_Succ;
  86.  
  87.         /* Is this a shared lock? */
  88.         if((ULONG)on->node.ln_Name!=SM_EXCLUSIVE)
  89.         {
  90.             /* Yes. Remove it from the list */
  91.             Remove(&on->node);
  92.  
  93.             /* Wake the new owner. Check access type. */
  94.             if(on->node.ln_Pri==SN_TYPE_OBTAIN)
  95.             /* ObtainSemaphore() type. Send the semaphore signal. */
  96.             Signal(on->task,SEMAPHORESIGF);
  97.             else
  98.             {
  99.             /* Procure() type. Reply the semaphore message. */
  100.             ((struct SemaphoreMessage *)on)->ssm_Semaphore=sigSem;
  101.             ReplyMsg((struct Message *)on);
  102.             }
  103.  
  104.             /*
  105.             Mark the semaphore as having one more openers.
  106.             This happens here because the new owner(s) may need
  107.             some time to really wake up and I don't want other
  108.             tasks obtaining the semaphore before him.
  109.             */
  110.             sigSem->ss_NestCount--;
  111.         }
  112.         /* Dito. Invalidate the owner field. */
  113.         sigSem->ss_Owner=NULL;
  114.         }
  115.     }else
  116.     {
  117.         /* The new owner wants an exclusive lock. Remove him from the list. */
  118.         Remove(&sn->node);
  119.  
  120.         /* Check access type */
  121.         if(sn->node.ln_Pri==SN_TYPE_OBTAIN)
  122.         {
  123.         /*
  124.             ObtainSemaphore() type. Set the owner field and
  125.             Send the semaphore signal.
  126.         */
  127.         sigSem->ss_Owner=sn->task;
  128.         Signal(sn->task,SEMAPHORESIGF);
  129.         }else
  130.         {
  131.         /* Procure() type. Reply the message. */
  132.         ((struct SemaphoreMessage *)sn)->ssm_Semaphore=sigSem;
  133.         sigSem->ss_Owner=((struct Message *)sn)->mn_ReplyPort->mp_SigTask;
  134.         ReplyMsg((struct Message *)sn);
  135.         }
  136.         /* Mark the semaphore as having one more openers. */
  137.         sigSem->ss_NestCount++;
  138.     }
  139.     }
  140.  
  141.     /* All done. */
  142.     Permit();
  143.     __AROS_FUNC_EXIT
  144. } /* ReleaseSemaphore */
  145.